Skip to content

feat: warn on unsaved changes#259

Merged
TatjanaTrajkovic merged 2 commits into
mainfrom
feature/journal_text_issuse
Apr 23, 2026
Merged

feat: warn on unsaved changes#259
TatjanaTrajkovic merged 2 commits into
mainfrom
feature/journal_text_issuse

Conversation

@TatjanaTrajkovic

@TatjanaTrajkovic TatjanaTrajkovic commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

when leaving case-detail
(#217)

Summary by CodeRabbit

  • New Features
    • Added confirmation prompts when attempting to navigate away from a case with unsaved changes.
    • Added protection against accidentally closing the browser with unsaved messages or edits.
    • Auto-saves case edits when navigating away.

  when leaving case-detail
  (#217)
@TatjanaTrajkovic TatjanaTrajkovic self-assigned this Apr 23, 2026
@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@TatjanaTrajkovic has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 44 minutes and 33 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 44 minutes and 33 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3c83c27a-209b-4616-b6e4-eb58ab213c2c

📥 Commits

Reviewing files that changed from the base of the PR and between a2870ce and 8128212.

📒 Files selected for processing (1)
  • frontend/src/pages/CaseDetail.jsx
📝 Walkthrough

Walkthrough

This pull request introduces unsaved changes detection and navigation blocking for the case detail view. The App component uses a ref to track dirty state and blocks in-app navigation when changes exist, while CaseDetail reports edit status and auto-saves on unmount.

Changes

Cohort / File(s) Summary
Navigation State Management
frontend/src/App.jsx
Introduces caseDetailDirtyRef to track unsaved changes without triggering re-renders. Integrates an onNavigate callback in Layout that blocks view switching from case-detail when dirty, requiring user confirmation via window.confirm before allowing navigation.
Dirty State Reporting & Auto-Save
frontend/src/pages/CaseDetail.jsx
Adds onDirtyChange callback prop to report edit status upward based on pending message text or journal editing. Registers beforeunload handler to prevent full page navigation with unsaved changes. On component unmount, resets dirty state and triggers automatic save of edited title and description.

Sequence Diagram

sequenceDiagram
    actor User
    participant App
    participant CaseDetail
    participant MedicalRecordService

    User->>CaseDetail: Edit title/description or type message
    CaseDetail->>App: onDirtyChange(true)
    App->>App: Update caseDetailDirtyRef.current
    
    User->>App: Attempt to navigate away from case-detail
    App->>App: Check caseDetailDirtyRef.current
    
    alt Dirty state is true
        App->>User: Show confirmation dialog
        alt User confirms
            User->>App: Click OK
            App->>App: Clear caseDetailDirtyRef.current
            App->>CaseDetail: Trigger unmount
        else User cancels
            User->>App: Click Cancel
            Note over App: Navigation blocked
        end
    else Dirty state is false
        App->>CaseDetail: Proceed with unmount
    end
    
    CaseDetail->>App: onDirtyChange(false)
    CaseDetail->>MedicalRecordService: Auto-save edited title & description
    MedicalRecordService-->>CaseDetail: Update complete (or error ignored)
    CaseDetail->>User: Component unmounted
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A carrot so green, left unsaved in the field,
Now guarded by guards, our dear edits are sealed!
With refs and callbacks, we track every bite,
No navigation without the user's all-right! 🛡️✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: warn on unsaved changes' directly and clearly summarizes the main objective of the changeset—implementing a warning feature when users attempt to leave the case-detail view with unsaved changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/journal_text_issuse

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/App.jsx (1)

112-123: ⚠️ Potential issue | 🟠 Major

In-page "Tillbaka" button bypasses the unsaved-changes prompt.

onNavigate (lines 276–282) guards Layout-level navigation with window.confirm, but goBackToDashboard — invoked by CaseDetail's back button and by onGoToPet — unconditionally clears caseDetailDirtyRef.current and changes the view. Users leaving via the back arrow or the patient-card link will never see the warning, and (combined with the unmount auto-save in CaseDetail.jsx) their edits will be silently persisted.

Consider centralizing the guard:

♻️ Suggested change
 const goBackToDashboard = () => {
+    if (currentView === 'case-detail' && caseDetailDirtyRef.current) {
+        if (!window.confirm('Du har osparade ändringar. Vill du lämna sidan?')) return;
+    }
     caseDetailDirtyRef.current = false;
     setSelectedPet(null);
     ...
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/App.jsx` around lines 112 - 123, The goBackToDashboard handler
unconditionally clears caseDetailDirtyRef.current and switches views, bypassing
the unsaved-changes guard implemented in onNavigate; update goBackToDashboard
(and any callers such as onGoToPet/CaseDetail back actions) to reuse the same
confirmation logic as onNavigate by checking caseDetailDirtyRef.current and
calling window.confirm before clearing the ref and calling
setCurrentView/setSelectedPet/setSelectedRecord, or refactor the onNavigate
guard into a shared helper (e.g., confirmAndNavigate) and call that from
goBackToDashboard so all in-page navigations prompt consistently.
🧹 Nitpick comments (1)
frontend/src/App.jsx (1)

276-282: Nit: onNavigate re-creates on every render.

The inline arrow is fine functionally, but since Layout likely passes it to nav items, it forces them to re-render each time. Wrapping in useCallback (with dependency on currentView) would be a cheap improvement. Optional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/App.jsx` around lines 276 - 282, The inline onNavigate arrow
prop re-creates every render causing child re-renders; extract it into a stable
callback using React.useCallback (e.g. create a handleNavigate that contains the
current logic referencing currentView, caseDetailDirtyRef.current and
setCurrentView) and pass that handleNavigate to Layout/onNavigate with
dependencies set to [currentView] (refs need not be in deps) so the function
identity is stable across renders.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/pages/CaseDetail.jsx`:
- Around line 54-65: The cleanup effect currently auto-saves silently on unmount
(useEffect cleanup) by calling medicalRecordService.update with
editedTitleRef/editedDescriptionRef and swallowing errors, which causes
unexpected persistence and lost error visibility; change the cleanup so it does
NOT auto-save by default — only clear the dirty flag via onDirtyChange(false)
and avoid calling medicalRecordService.update unless an explicit
opt-in/draft-save flag is present (or the user clicked an explicit “save”
action), and if you must call update then surface failures (show
toast/console.error) instead of .catch(()=>{}); also add caseData to the effect
deps (or guard against missing caseData in cleanup) so caseData.id is not
dereferenced if falsy at mount.
- Around line 36-39: The current dirty-state logic marks the form dirty whenever
isEditing is true even if editedTitle/editedDescription match caseData, so
update the useEffect that calls onDirtyChange (and the similar beforeunload
handler and unmount auto-save guard) to compute dirty as:
newMessage.trim().length > 0 OR (isEditing AND (editedTitle !== caseData.title
OR editedDescription !== caseData.description)); replace the simple isEditing
check with this comparison so entering edit mode without changes does not set
the dirty flag and apply the same comparison logic to the beforeunload and
on-unmount autosave guards.

---

Outside diff comments:
In `@frontend/src/App.jsx`:
- Around line 112-123: The goBackToDashboard handler unconditionally clears
caseDetailDirtyRef.current and switches views, bypassing the unsaved-changes
guard implemented in onNavigate; update goBackToDashboard (and any callers such
as onGoToPet/CaseDetail back actions) to reuse the same confirmation logic as
onNavigate by checking caseDetailDirtyRef.current and calling window.confirm
before clearing the ref and calling
setCurrentView/setSelectedPet/setSelectedRecord, or refactor the onNavigate
guard into a shared helper (e.g., confirmAndNavigate) and call that from
goBackToDashboard so all in-page navigations prompt consistently.

---

Nitpick comments:
In `@frontend/src/App.jsx`:
- Around line 276-282: The inline onNavigate arrow prop re-creates every render
causing child re-renders; extract it into a stable callback using
React.useCallback (e.g. create a handleNavigate that contains the current logic
referencing currentView, caseDetailDirtyRef.current and setCurrentView) and pass
that handleNavigate to Layout/onNavigate with dependencies set to [currentView]
(refs need not be in deps) so the function identity is stable across renders.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f2c63ad0-ee58-412e-8ac1-72a0457a0ca6

📥 Commits

Reviewing files that changed from the base of the PR and between 8ef036c and a2870ce.

📒 Files selected for processing (2)
  • frontend/src/App.jsx
  • frontend/src/pages/CaseDetail.jsx

Comment thread frontend/src/pages/CaseDetail.jsx Outdated
Comment thread frontend/src/pages/CaseDetail.jsx Outdated
@TatjanaTrajkovic TatjanaTrajkovic added enhancement New feature or request frontend labels Apr 23, 2026
@TatjanaTrajkovic
TatjanaTrajkovic merged commit f94a3c3 into main Apr 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Journaltext försvinner när man byter flik utan att klicka Spara/Skicka

1 participant